#include "rfid_reader_hf.h"

using namespace RFIDLIB;
using namespace std;
CRFID_READER_HF::CRFID_READER_HF()
{
    RDType_ID = RDTYPE_HF;
}

CRFID_READER_HF::~CRFID_READER_HF()
{
    Close();
}

void CRFID_READER_HF::AddNewISO15693Tag(UINT32 apl_tid,UINT32 picc_tid,UINT32 ant_id,UINT8 dsfid,UINT8 *uid,USHORT rssi)
{
    CString tagtype;
    if(picc_tid == RFID_ISO15693_PICC_ICODE_SLI_ID )
    {
        tagtype =_T("NXP ICODE SLI");
    }
    else if(picc_tid ==RFID_ISO15693_PICC_TI_HFI_PLUS_ID)
    {
        tagtype = _T("Ti HF-I Plus");
    }
    else if(picc_tid ==RFID_ISO15693_PICC_ST_M24LR64_ID )
    {
        tagtype =_T("ST M24LR64");
    }
    else if(picc_tid == RFID_ISO15693_PICC_ST_M24LR16E_ID)
    {
        tagtype=_T("ST M24LR16E");
    }
    else if(picc_tid ==RFID_ISO15693_PICC_ST25TV02K_ID) {
        tagtype =_T("ST25TV02K");
    }
    else if(picc_tid == RFID_ISO15693_PICC_FUJ_MB89R118C_ID)
    {
        tagtype =_T("Fujitsu MB89R118C");
    }
    else if(picc_tid== RFID_ISO15693_PICC_ICODE_SLIX_ID)
    {
        tagtype=_T("NXP ICODE SLIX");
    }
    else if(picc_tid== RFID_ISO15693_PICC_TIHFI_STANDARD_ID)
    {
        tagtype=_T("Ti HF-I Standard");
    }
    else if(picc_tid == RFID_ISO15693_PICC_TIHFI_PRO_ID)
    {
        tagtype=_T("Ti HF-I Pro");
    }
    else if(picc_tid == RFID_ISO15693_PICC_ICODE_SLIX2_ID){
        tagtype == _T("NXP ICODE SLIX2");
    }
    else
    {
        tagtype  =_T("Unknown Tag");
    }
    CHAR suid[32];
    memset(suid,0,sizeof(suid));
    BytesToHexStr(uid,8,suid);
    CHAR sdsfid[8];
    memset(sdsfid,0,sizeof(sdsfid));
    BytesToHexStr(&dsfid,1,sdsfid);
    CString sAntId;
    sAntId.Format(_T("%d"),ant_id);
    UINT32 i;
    CTag_HF* pTag;
    for( i=0;i<m_tags_hf.size();i++)
    {
        pTag=(CTag_HF*)&m_tags_hf.at(i);
        if(pTag->m_uid ==suid && pTag->m_antNo == ant_id)
        {
            break;
        }
    }
    if(i>=m_tags_hf.size())
    {
        CTag_HF newtag;
        newtag.m_counter = 1;
        newtag.m_uid =suid;
        newtag.m_type = picc_tid;
        newtag.m_antNo =ant_id;
        newtag.m_AIP =apl_tid ;
        newtag.m_rssi=rssi;
        m_tags_hf.push_back(newtag);
    }
    else
    {
        pTag->m_counter++;
        pTag->m_rssi=rssi;
        if(pTag->m_counter>=500000)
        {
            pTag->m_counter = 1;
        }
    }
}

void CRFID_READER_HF::AddNewISO14443ATag(UINT32 apl_tid,UINT32 picc_tid,UINT32 ant_id,UINT8 *uid,UINT8 uidlen)
{
    CString tagtype;
    switch(picc_tid)
    {
    case RFID_ISO14443A_PICC_NXP_ULTRALIGHT_ID:
        tagtype =_T("NXP Mifare Ultralight");
        break;
    case RFID_ISO14443A_PICC_NXP_MIFARE_S50_ID:
        tagtype =_T("NXP Mifare S50");
        break;
    case RFID_ISO14443A_PICC_NXP_MIFARE_S70_ID:
        tagtype =_T("NXP Mifare S70");
        break;
    default:
        tagtype =_T("unknown tag");

    }
    CHAR c_uid[32];
    memset(c_uid,0,sizeof(c_uid));
    BytesToHexStr(uid,uidlen,c_uid);

    CString suid;
    suid.Format(_T("%s"),c_uid);
    INT32 i;
    CTag_HF* pTag;
    for( i=0;i<m_tags_hf.size();i++)
    {
        pTag=(CTag_HF*)&m_tags_hf.at(i);
        if(pTag->m_uid == suid && pTag->m_antNo == ant_id)
        {
            break;
        }
    }
    if(i>=m_tags_hf.size())
    {
        CTag_HF newtag;
        newtag.m_counter = 1;
        newtag.m_uid =suid;
        newtag.m_type = picc_tid;
        newtag.m_antNo =ant_id;
        newtag.m_AIP =apl_tid ;
        newtag.m_rssi=0;
        m_tags_hf.push_back(newtag);
    }
    else
    {
        pTag->m_counter++;
        if(pTag->m_counter>=500000)
        {
            pTag->m_counter = 1;
        }
    }
}


err_t CRFID_READER_HF::func_Inventory()
{
    err_t iret;
    if(this->ant_count<=0)
        return -ERR_ARG;
    BYTE newAI= AI_TYPE_NEW;

    //RDR_DisableAsyncTagReportOutput(hRdr);// disable async tag report output

    RFID_DN_HANDLE dnInvenParamList= RFID_HANDLE_NULL;
    dnInvenParamList = RDR_CreateInvenParamSpecList();
    if(dnInvenParamList)
    {
        if((air_type&AIR_ISO15693)>0)
        {
            ISO15693_CreateInvenParam(dnInvenParamList,0,FALSE,0,0x00);
        }
        if((air_type&AIR_ISO14443A)>0)
        {
            ISO14443A_CreateInvenParam(dnInvenParamList,0);
        }
    }
    else
        return -ERR_MEM;

    iret = RDR_TagInventory(hRdr,newAI,this->ant_count,this->antennas,dnInvenParamList);
    if(iret == NO_ERR || iret == -ERR_STOPTRRIGOCUR)
    {
        RFID_DN_HANDLE dnhReport = RDR_GetTagDataReport(hRdr,RFID_SEEK_FIRST);
        while(dnhReport != RFID_HANDLE_NULL)
        {
            DWORD AIPtype,TagType,AntId,readCount;
            BYTE dsfid;
            WORD rssi;
            BYTE uid[8];
            BYTE uidlen;
            int rtn= ISO15693_ParseTagDataReportEx(dnhReport,&AIPtype,&TagType,&AntId,&dsfid,&rssi,&readCount,uid);
            if(rtn == NO_ERR)
            {
                AddNewISO15693Tag(AIPtype,TagType,AntId,dsfid,uid,rssi);
            }
            rtn = ISO14443A_ParseTagDataReport(dnhReport,&AIPtype,&TagType,&AntId,uid,&uidlen);
            if(rtn  == NO_ERR)
            {
                AddNewISO14443ATag(AIPtype,TagType,AntId ,uid, uidlen);
            }
            dnhReport = RDR_GetTagDataReport(hRdr,RFID_SEEK_NEXT);
        }
        if (iret == -ERR_STOPTRRIGOCUR) // stop trigger occur,need to inventory left tags
            iret = NO_ERR;
    }
    if(dnInvenParamList)
    {
        DNODE_Destroy(dnInvenParamList);
    }
    return iret;
}

//Write Blocks
err_t CRFID_READER_HF::func_AccessTag_WriteData(CTag &tag,DWORD block_addr,DWORD block_num,BYTE* data,DWORD dlen)
{
    int iret = 0;
    RFID_TAG_HANDLE ht=NULL;
    iret = AccessTag_Connect(tag, &ht);
    if(ht == NULL)
        return -ERR_NOCMD;//TAG COMMAND NOT SUPPORT
    if(iret == NO_ERR)
    {
        iret = ISO15693_WriteMultipleBlocks(hRdr,ht,block_addr,block_num,data,dlen);
        AccessTag_Disconnect(tag,ht);
    }
    ht=NULL;
    return iret;
}

//Read Blocks
err_t CRFID_READER_HF::func_AccessTag_ReadData(CTag &tag,DWORD block_addr,DWORD block_num,BYTE* data,DWORD *dlen)
{
    int iret = 0;
    RFID_TAG_HANDLE ht=NULL;
    iret = AccessTag_Connect(tag, &ht);
    if(ht == NULL)
        return -ERR_NOCMD;//TAG COMMAND NOT SUPPORT
    if(iret == NO_ERR)
    {
        bool read_secsta=false;
        DWORD numOfBlks_Readed=block_num;
        DWORD nSize=(read_secsta?block_num*5:block_num*4);
        BYTE* buffer=new BYTE[nSize];
        DWORD byts_read_out=0;
        iret=ISO15693_ReadMultiBlocks(hRdr,ht,read_secsta,block_addr,block_num,&numOfBlks_Readed,buffer,nSize,&byts_read_out);
        if(iret != NO_ERR)
        {
            delete[] buffer;
            AccessTag_Disconnect(tag,ht);
            return iret;
        }
        if(block_num != numOfBlks_Readed)
        {
            delete[] buffer;
            AccessTag_Disconnect(tag,ht);
            return iret;
        }
        if(*dlen>=nSize)
            *dlen=nSize;
        if(*dlen>=byts_read_out)
            *dlen=byts_read_out;
        memcpy(data,buffer,*dlen);
        delete[] buffer;

        AccessTag_Disconnect(tag,ht);
    }
    ht=NULL;
    return iret;
}

//Enable/Disable ESA
err_t CRFID_READER_HF::func_AccessTag_EnDisable_EAS(CTag &tag,bool bEnable)
{
    int iret = 0;
    RFID_TAG_HANDLE ht=NULL;
    iret = AccessTag_Connect(tag, &ht);
    if(ht == NULL)
        return -ERR_NOCMD;//TAG COMMAND NOT SUPPORT
    if(iret == NO_ERR)
    {
        if(bEnable)
            iret=NXPICODESLI_EableEAS(hRdr,ht);
        else
            iret=NXPICODESLI_DisableEAS(hRdr,ht);
        AccessTag_Disconnect(tag,ht);
    }
    ht=NULL;
    return iret;
}
//Check ESA
err_t CRFID_READER_HF::func_AccessTag_Check_EAS(CTag &tag,BYTE &eas_sta)
{
    int iret = 0;
    RFID_TAG_HANDLE ht=NULL;
    iret = AccessTag_Connect(tag, &ht);
    if(ht == NULL)
        return -ERR_NOCMD;//TAG COMMAND NOT SUPPORT
    if(iret == NO_ERR)
    {
        iret=NXPICODESLI_EASCheck(hRdr,ht,&eas_sta);
        AccessTag_Disconnect(tag,ht);
    }
    ht=NULL;
    return iret;
}

//Read or Write AFI
//bRead: true=Read AFI,else Write AFI
err_t CRFID_READER_HF::func_AccessTag_Write_AFI(CTag &tag,BYTE afi)
{
    int iret = 0;
    RFID_TAG_HANDLE ht=NULL;
    iret = AccessTag_Connect(tag, &ht);
    if(ht == NULL)
        return -ERR_NOCMD;//TAG COMMAND NOT SUPPORT
    if(iret == NO_ERR)
    {
        iret= ISO15693_WriteAFI(hRdr,ht,(BYTE)afi);
        AccessTag_Disconnect(tag,ht);
    }
    ht=NULL;
    return iret;
}

//Get tag's information about:
//SDFID AFI BLOCK_SIZE BLOCK_NUMBERS
err_t CRFID_READER_HF::func_AccessTag_GetInfor(CTag &tag,BYTE *dsfid, BYTE *afi,DWORD *block_size,DWORD *block_num, BYTE *ic_ref)
{
    BYTE uid[8]={0};

//    BYTE dsfid_1;
//    BYTE afi;
//    DWORD block_size;
//    DWORD block_num;
//    BYTE ic_ref;

    int iret = 0;
    RFID_TAG_HANDLE ht=NULL;
    iret = AccessTag_Connect(tag, &ht);
    if(ht == NULL)
        return -ERR_NOCMD;//TAG COMMAND NOT SUPPORT
    if(iret == NO_ERR)
    {
        iret=ISO15693_GetSystemInfo(hRdr,ht,uid,dsfid,afi,block_size,block_num,ic_ref);
        AccessTag_Disconnect(tag,ht);
    }
    ht=NULL;
    return iret;
}
err_t CRFID_READER_HF::AccessTag_ResetAntenna(BYTE mAnt)
{
    RDR_ResetBackupAntenna(hRdr);

    RFID_TAG_HANDLE ht=NULL;
    int iret=ISO15693_Connect(hRdr,RFID_ISO15693_PICC_ICODE_SLI_ID,0,NULL,&ht);
    if(iret != NO_ERR)
    {
        ht=NULL;
        return iret;
    }
    RDR_SetAcessAntenna(hRdr,mAnt);
    iret=ISO15693_Reset(hRdr,ht);
    if(iret != NO_ERR)
    {
        if(ht!=NULL)
            RDR_TagDisconnect(hRdr,ht);
        return iret;
    }
    return iret;
}
err_t CRFID_READER_HF::AccessTag_Connect(CTag &tag,RFID_TAG_HANDLE *ht)
{
    CTag_HF* pTag=(CTag_HF*)&tag;
    const int ulen=pTag->m_uid.length()>2?pTag->m_uid.length()/2:0;
    BYTE byts[ulen];
    memset(byts,0,ulen);
    int blen=0;
    HexStrToBytes(pTag->m_uid.data(),byts,blen);
    DWORD type=pTag->m_type;
    BYTE addr_mode=0x01;
    int iret=0;

    iret=RDR_SetAcessAntenna(hRdr,(BYTE)(pTag->m_antNo<1?1:pTag->m_antNo));

    if(pTag->m_AIP==RFID_APL_ISO15693_ID)
    {
        iret=ISO15693_Connect(hRdr,type,addr_mode,byts, ht);

        if(iret != NO_ERR || *ht == NULL)
            AccessTag_ResetAntenna(pTag->m_antNo<1?1:pTag->m_antNo);
    }
    else if(pTag->m_AIP==RFID_APL_ISO14443A_ID || pTag->m_AIP == RFID_APL_ISO14443B_ID )
    {
        iret=ISO14443A_Connect(hRdr,type,byts,blen, ht);
        if(iret != NO_ERR || *ht == NULL)
            AccessTag_ResetAntenna(pTag->m_antNo<1?1:pTag->m_antNo);
    }
    else
    {
        return -ERR_NOCMD;
    }
    return iret;
}

inline err_t CRFID_READER_HF::AccessTag_Disconnect(CTag &tag,RFID_TAG_HANDLE ht)
{
    if(ht == NULL) return NO_ERR;
    int iret=RDR_TagDisconnect(hRdr,ht);
    if(iret!= NO_ERR)
        return iret;
   // AccessTag_ResetAntenna(pTag->m_antNo<1?1:pTag->m_antNo);
}
